//////////////////////////////////////////////////////////////////////
//
// NO_OArchive.cpp interface for the NO_OArchive class.
//
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
#define NO_TAL_EXPORT

//////////////////////////////////////////////////////////////////////////
#include "NO_Externs.h"
#include "NO_OArchive.h"

//////////////////////////////////////////////////////////////////////////
// use
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
NO_OArchive& NO_OArchive::operator<<(NO_Object& object) 
{
	try{range(object);}
	catch (std::bad_cast& e)	{std::cout<<e.what()<<std::endl;}
	catch (std::bad_typeid& e)	{std::cout<<e.what()<<std::endl;}
	catch (std::exception& e)	{std::cout<<e.what()<<std::endl;}
	catch (...)					{std::cout<<"NO_OArchive failed"<<std::endl;}

	return *this;
}

//////////////////////////////////////////////////////////////////////////
// use
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
NO_OArchive& NO_OArchive::objectBegin(NO_Object& object)
{
	if(!stream){throw std::exception("NO_OArchive: stream empty");}
	if(!object){return emptyBegin();}
	registerObject(object,object.getID());
	writeBegin(object);
	return *this;
}

//////////////////////////////////////////////////////////////////////////
NO_OArchive& NO_OArchive::objectEnd(NO_Object& object)
{
	if(!stream){throw std::exception("NO_OArchive: stream empty");}
	if(!object){return emptyEnd();}
	writeEnd(object);
	return *this;
}

//////////////////////////////////////////////////////////////////////////
NO_OArchive& NO_OArchive::emptyBegin(void)
{
	if(!stream){throw std::exception("NO_OArchive: stream empty");}
	writeBegin(NO_Object::empty);
	return *this;
}

//////////////////////////////////////////////////////////////////////////
NO_OArchive& NO_OArchive::emptyEnd(void)
{
	if(!stream){throw std::exception("NO_OArchive: stream empty");}
	writeEnd(NO_Object::empty);
	return *this;
}

//////////////////////////////////////////////////////////////////////////
// use
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
NO_OArchive& NO_OArchive::range(NO_Object& object)
{
	if(!stream){throw std::exception("NO_OArchive: stream empty");}
	if(!object){return emptyBegin().emptyEnd();}
	
	NO_Object found = findObject(object.getID());
	if(found&&found.getType()==object.getType())
	{if(!doReferences){return writeBegin(found).writeEnd(found);}}

	NO_UInt32 num = object.getNum();
	if(num==1){return object.getType().output(object,*this);}

	objectBegin(object);
	for(NO_UInt32 i = 0; i<num; i++)
	{
		NO_Object element = object.element(i);
		element.getType().output(element,*this);
	}
	objectEnd(object);

	return *this;
}

//////////////////////////////////////////////////////////////////////////
NO_OArchive& NO_OArchive::bases(NO_Object& object)
{
	if(!stream){throw std::exception("NO_OArchive: stream empty");}
	if(!object){throw std::exception("NO_OArchive: object empty");}

	const NO_Type& type = object.getType();
	const NO_IBase* bIter = type.beginBase();
	const NO_IBase* bEnd = type.endBase();
	while (bIter!=bEnd)
	{
		NO_Object base(object.base(*bIter));
		members(base);
		bIter = type.nextBase(bIter);
	}
	
	return *this;
}

//////////////////////////////////////////////////////////////////////////
NO_OArchive& NO_OArchive::members(NO_Object& object)
{
	if(!stream){throw std::exception("NO_OArchive: stream empty");}
	if(!object){throw std::exception("NO_OArchive: object empty");}

	const NO_Type& type = object.getType();
	const NO_IMember * iter = type.beginMember();
	const NO_IMember * end = type.endMember();
	while (iter!=end)
	{
		NO_Object member = object.member(*iter);
		range(member);
		iter = type.nextMember(iter);
	}
	return *this;
}

//////////////////////////////////////////////////////////////////////////
NO_OArchive& NO_OArchive::functions(NO_Object& object){return *this;}
NO_OArchive& NO_OArchive::memberFunctions(NO_Object& object){return *this;}

